package com.yizhuoyan.his.algorithm;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Base64 {
	private static final int B24_0 = 0b111111;
	private static final int B24_6 = 0b1111_11000000;
	private static final int B24_12 = 0b11_11110000_00000000;
	private static final int B24_18 = 0b11111100_00000000_00000000;
	private static final int B16_10 = 0b11111100_00000000;
	private static final int B16_4 = 0b11_11110000;
	private static final int B16_0 = 0b1111;
	private static final int B8_2 = 0b11111100;
	private static final int B8_0 = 0b11;

	private static final char[] CHARS_STANDARD = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
			.toCharArray();
	private static final char[] CHARS_FOR_URL = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_="
			.toCharArray();

	

	static public String encodingURL(byte[] data) {
		return encoding(data, CHARS_FOR_URL);
	}

	static public String encoding(byte[] data) {
		return encoding(data, CHARS_STANDARD);
	}

	static private String encoding(byte[] data, char[] chars) {
		int resultBytes = data.length / 3;
		int left = data.length % 3;
		if (left != 0) {
			resultBytes++;
		}
		resultBytes = resultBytes * 4;
		StringBuilder result = new StringBuilder(resultBytes);
		int i = 0;
		for (int len = data.length - left; i < len; result.append(encoding(chars, data[i++], data[i++], data[i++])))
			;
		if (left == 1) {
			result.append(encoding(chars, data[i]));
		} else if (left == 2) {
			result.append(encoding(chars, data[i++], data[i]));
		}
		return result.toString();
	}

	private static char[] encoding(char[] chars, byte a, byte b, byte c) {
		int b24 = (a & 0xff) << 16 | (b & 0xff) << 8 | (c & 0xff);
		char[] result = new char[4];
		result[0] = chars[(b24 & B24_18) >>> 18];
		result[1] = chars[(b24 & B24_12) >>> 12];
		result[2] = chars[(b24 & B24_6) >>> 6];
		result[3] = chars[b24 & B24_0];
		return result;
	}
	
	
	private static byte[] decoding(String s,int begin) {
		byte a=char2byte(s.charAt(begin++));
		byte b=char2byte(s.charAt(begin++));
		byte c=char2byte(s.charAt(begin++));
		byte d=char2byte(s.charAt(begin));
		
		int b24=(a&0xff)<<18|(b&0xff)<<12|(c&0xff)<<6|(d&0xff);
		
		byte[] data=new byte[3];
		data[0]=(byte)((b24&0xff0000)>>>16);
		data[1]=(byte)((b24&0xff00)>>>8);
		data[2]=(byte)(b24&0xff);
		return data;
	}
	private static byte char2byte(char c) {
		if('A'<=c&&c<='Z') {
			return (byte)(c-'A');
		}
		if('a'<=c&&c<='z') {
			return (byte)((c-'a')+26);
		}
		if('0'<=c&&c<='9') {
			return (byte)((c-'0')+52);
		}
		if(c=='+'||c=='-') {
			return 62;
		}
		if(c=='/'||c=='_') {
			return 63;
		} 
		if(c=='=') {
			return 64;
		}
		throw new RuntimeException();
        
	}  
	
	private static char[] encoding(char[] chars, byte a, byte b) {
		int b16 = (a & 0xff) << 8 | (b & 0xff);
		char[] result = new char[4];
		result[0] = chars[(b16 & B16_10) >>> 10];
		result[1] = chars[(b16 & B16_4) >>> 4];
		result[2] = chars[(b16 & B16_0) << 2];
		result[3] = chars[CHARS_STANDARD.length - 1];
		
		return result;
	}

	private static char[] encoding(char[] chars, byte a) {
		int b8 = (a & 0xff);
		char[] result = new char[4];
		result[0] = chars[(b8 & B8_2) >>> 2];
		result[1] = chars[(b8 & B8_0) << 4];
		result[2] = chars[CHARS_STANDARD.length - 1];
		result[3] = result[2];  
		return result;
	}

	public static String decoding(String s, String charset) {
		try {
		    int length=s.length();
			ByteArrayOutputStream out = new ByteArrayOutputStream();
			for(int i=0;i<length;i+=4) {
				out.write(decoding(s, i));
			}
			return out.toString(charset);
		}catch(Exception e) {
			throw new IllegalArgumentException(e);
		}
	}
	public static void main(String[] args) {
		String s="abas(aa(abc)))";
		Pattern p=Pattern.compile("\\(.*\\)");
		Matcher matcher=null;
		while((matcher=p.matcher(s)).find()) {
			s=matcher.replaceAll("");
		}
		System.out.println(s);
		
	}
}
